/*
 * SQLiteDb.h
 *
 *  Created on: 2011-4-18
 *      Author: wanghuan
 *      */

#ifndef SQLiteDB_H_
#define SQLiteDB_H_

#include "sqlite3.h"
#include <e32def.h>

class SQLiteResultSet
{
public:
    ~SQLiteResultSet();
    SQLiteResultSet();
    SQLiteResultSet(const SQLiteResultSet &other);
    SQLiteResultSet& operator=(const SQLiteResultSet& other); 
    SQLiteResultSet(sqlite3 * pdb, sqlite3_stmt * pstmt, bool eof, bool ownStmt);
    bool HasNext();
    void Next();
    void Finalize();
    
    const char * GetString(int idx, const char * nullValue = NULL);
    const char * GetString(const char * colname, const char * nullValue = NULL);
    
    int GetInt(int idx, int nullValue = 0);
    int GetInt(const char * colname, int nullValue = 0);
    
    double GetFloat(int idx, double nullValue = 0);
    double GetFloat(const char * colname, double nullValue = 0);
    
    unsigned char * GetBlob(int idx, int &len);
    unsigned char * GetBlob(const char * colname, int &len);
    
private:
    bool m_eof;
    bool m_ownStmt;
    sqlite3 * m_pdb;
    int m_cols;
    sqlite3_stmt * m_pstmt;
    int GetColumnIndex(const char * colname);
    int FieldDataType(int idx);
};

class SQLiteStatement
{
public:
	~SQLiteStatement();
	SQLiteStatement &operator = (const SQLiteStatement &);
	SQLiteStatement(const SQLiteStatement &);
    SQLiteStatement(sqlite3 * pdb, sqlite3_stmt * pstmt);
    SQLiteResultSet Query();
    void Execute();
    void Bind(int idx, const char * value);
    void Bind(int idx, const int value);
    void Bind(int idx, const double value);
    void Bind(int idx, const unsigned char * blob, int len);
    void BindNull(int idx);
    void Reset();
    void Finalize();
    
private:
    void HandleResult(int rc);
    sqlite3 * m_pdb;
    sqlite3_stmt * m_pstmt;
};

class SQLiteDbManager
{
public:
    ~SQLiteDbManager();
    static SQLiteDbManager * GetInstance();
    void Open(const char * szFile);
    void Close();
    void SetBusyTimeout(int nMillisecs);
    
    void BeginTransaction();
    void EndTransaction();
    /*
     * perform an insert, delete, select or update
     */
    SQLiteResultSet Query(const char * format, ...);
    
    /*
     * same as Query, except ignoring the results  
     */
    void Execute(const char * format, ...);
    /*
     * get the number of affected rows that last query made,
     * should always be used with Execute 
     */
    int GetAffectedRows();
    /*
     * test whether a table exists or not
     */
    bool IsTableExists(const char * table);
    /*
     * get last row id
     */
    TInt64 GetLastRowId();
    
    SQLiteStatement CompileStatement(const char * format, ...);
    
private:
    static SQLiteDbManager * s_instance;
    sqlite3 * m_pdb;
    int m_busyTimeout;
    SQLiteResultSet rs;
    
private:
    SQLiteDbManager();
    SQLiteDbManager(const SQLiteDbManager &db);
    SQLiteDbManager& operator= (const SQLiteDbManager &db);
    sqlite3_stmt* Compile(const char * sql);
};

#endif /* SQLiteDB_H_ */
